/*
类的继承
语法： class 子类: 继承方式 父类  或  class 子类 ：继承方式 父类1 ， 继承方式 父类2...
继承方式有：公共继承，保护继承，私有继承
C++实际开发中不建议用多继承

父类中私有成员也是被子类继承下去了，只是由编译器给隐藏后访问不到

继承中 先调用父类构造函数，再调用子类构造函数，析构顺序与构造相反

当子类与父类出现同名的成员时：
  子类对象可以直接访问到子类中同名成员
  子类对象加作用域可以访问到父类同名成员
  当子类与父类拥有同名的成员函数，子类会隐藏父类中同名成员函数，加作用域可以访问到父类中同名函数

菱形(钻石)继承， B, C 两个类继承同一个父类A，D类有同时继承B，C 两个父类。这样会造成D类对A类继承了两次，
造成资源浪费。使用虚继承可以解决这个问题。
虚继承， 继承前加 virtual 关键字后， 变成虚继承，此时公共的父类变成虚基类。
class B: virtual public A {};
class C: virtual public A {};
class D:  public B, public C {};

*/
#include <iostream>
using namespace std;

class Base
{
public:
    int m_a;

    Base()
    {
        m_a = 100;
    }
    void func()
    {
        cout << "This is Base class func..." << endl;
    }
    void func(int a)
    {
        cout << "This is Base class func(int a)... a = " << a << endl;
    }

protected:
    int m_b;

private:
    int m_c;
};

class SonA : public Base
{
    // 继承结果：
    // public:
    //     int m_a;
    // protected:
    //     int m_b;
    // private:
    //     int m_c;
public:
    int m_a;  // 子类与父类定义了同名成员
    SonA()
    {
        m_a = 10;
    }

    // 子类与父类拥有同名函数，父类中的函数会被隐藏，如果想访问要加父类的作用域
    void func()
    {
        cout << "This is SonA class func..." << endl;
    }
};

class SonB : protected Base
{
    // 继承结果：
    //  protected:
    //      int m_a;
    //      int m_b;

    // private:
    //     int m_c;
};

class SonC : private Base
{
    // 继承结果：
    // private:
    //     int m_a;
    //     int m_b;
    //     int m_c;
};


int main ()
{
    SonA son;
    cout << "Accessing SonA member: m_a = " << son.m_a << endl;
    cout << "Accessing Base member: m_a = " << son.Base::m_a << endl;  // 加作用域访问父类的同名成员

    son.func();  // 访问子类的同名函数
    son.Base::func(); // 加作用域访问父类的同名函数
    son.Base::func(son.m_a);  // 加作用域访问父类的同名函数

    return 0;
}